import lombok.extern.slf4j.Slf4j;
import org.apache.http.HttpEntity;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;

import javax.net.ssl.KeyManager;
import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;
import javax.xml.bind.DatatypeConverter;
import java.io.*;
import java.security.KeyFactory;
import java.security.KeyStore;
import java.security.NoSuchAlgorithmException;
import java.security.cert.Certificate;
import java.security.cert.CertificateException;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import java.security.interfaces.RSAPrivateKey;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;

/**
 * @author by chuyiqi  2020/12/16 5:16 下午
 * <p></> TODO
 */
@Slf4j
public class SendSLL {

    private static String campaignUrl = "https://api.searchads.apple.com/api/v3/campaigns?limit=20&offset=0";// campaign
    //---------------------------------------------------------------------------------campaignId-----
    private static String adGroupUrl = "https://api.searchads.apple.com/api/v3/campaigns/452804038/adgroups";//广告组
    //------------------------------------------------------------------------------------------campaignId-----
    private static String negativekeywordsUrl = "https://api.searchads.apple.com/api/v3/campaigns/376982174/negativekeywords";//否定关键词
    //------------------------------------------------------------------------------------campaignId----------adgroupId-------
    private static String keywordsUrl = "https://api.searchads.apple.com/api/v3/campaigns/452804038/adgroups/452884856/targetingkeywords";//否定关键词

    private static String pemPath = "/Users/chuyiqi/Downloads/test_readonly/test_readonly.pem";
    private static String keypath = "/Users/chuyiqi/Downloads/test_readonly/test_readonly.key";

    public static void main(String[] args) {
        String s = httpGET(adGroupUrl, pemPath, keypath);
//        String s = httpPOST(adGroupUrl, pemPath, keypath);
        System.out.println("获取数据："+s);
    }

    private static String httpPOST(String url, String pemPath, String keypath) {
        String result = null;
        HttpPost httpPost = new HttpPost(url);
        // 根据默认超时限制初始化requestConfig
        RequestConfig requestConfig = RequestConfig.custom().setSocketTimeout(1000).setConnectTimeout(1000).build();
        // 设置请求器的配置
        httpPost.setConfig(requestConfig);
        // 加载证书
        CloseableHttpClient httpClient = null;
        try {
            SSLConnectionSocketFactory sslsf =getSocketFactoryPEM(pemPath, keypath);
            httpClient = HttpClients.custom().setSSLSocketFactory(sslsf).build();
        } catch (Exception e) {
            log.error(e.getMessage());
        }
        try {
            CloseableHttpResponse response = null;
            try {
                assert httpClient != null;
                response = httpClient.execute(httpPost);
            } catch (IOException e) {
                e.printStackTrace();
            }
            assert response != null;
            HttpEntity entity = response.getEntity();
            try {
                result = EntityUtils.toString(entity, "UTF-8");
            } catch (IOException e) {
                e.printStackTrace();
                log.error(e.getMessage());
            }
        } finally {
            httpPost.abort();
        }
        return result;
    }

    public static String httpGET(String url, String pemPath, String keypath) {
        String result = null;
        HttpGet httpGet = new HttpGet(url);
        // 根据默认超时限制初始化requestConfig
        RequestConfig requestConfig = RequestConfig.custom().setSocketTimeout(1000).setConnectTimeout(1000).build();
        // 设置请求器的配置
        httpGet.setConfig(requestConfig);
        // 加载证书
        CloseableHttpClient httpClient = null;
        try {
            SSLConnectionSocketFactory sslsf =getSocketFactoryPEM(pemPath, keypath);
            httpClient = HttpClients.custom().setSSLSocketFactory(sslsf).build();
        } catch (Exception e) {
            log.error(e.getMessage());
        }
        try {
            CloseableHttpResponse response = null;
            try {
                assert httpClient != null;
                response = httpClient.execute(httpGet);
            } catch (IOException e) {
                e.printStackTrace();
            }
            assert response != null;
            HttpEntity entity = response.getEntity();
            try {
                result = EntityUtils.toString(entity, "UTF-8");
            } catch (IOException e) {
                e.printStackTrace();
                log.error(e.getMessage());
            }
        } finally {
            httpGet.abort();
        }
        return result;
    }


    protected static SSLConnectionSocketFactory getSocketFactoryPEM(String pemPath, String keypath) throws Exception {
        byte[] pem = fileToBytes(pemPath);
        byte[] pemKey = fileToBytes(keypath);

        byte[] certBytes = parseDERFromPEM(pem, "-----BEGIN CERTIFICATE-----", "-----END CERTIFICATE-----");
        byte[] keyBytes = parseDERFromPEM(pemKey, "-----BEGIN PRIVATE KEY-----", "-----END PRIVATE KEY-----");

        X509Certificate cert = generateCertificateFromDER(certBytes);
        RSAPrivateKey key  = generatePrivateKeyFromDER(keyBytes);

        KeyStore keystore = KeyStore.getInstance("JKS");
        keystore.load(null);
        keystore.setCertificateEntry("cert-alias", cert);
        keystore.setKeyEntry("key-alias", key, "<password>".toCharArray(), new Certificate[] {cert});

        KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509");
        kmf.init(keystore, "<password>".toCharArray());

        KeyManager[] km = kmf.getKeyManagers();

        SSLContext context = SSLContext.getInstance("TLS");
        context.init(km, null, null);
        SSLConnectionSocketFactory sslsf =
                new SSLConnectionSocketFactory(context,null, null,
                        SSLConnectionSocketFactory.getDefaultHostnameVerifier());
        return sslsf;
    }

    public static byte[] parseDERFromPEM(byte[] pem, String beginDelimiter, String endDelimiter) {
        String data = new String(pem);
        String[] tokens = data.split(beginDelimiter);
        tokens = tokens[1].split(endDelimiter);
        return DatatypeConverter.parseBase64Binary(tokens[0]);
    }

    public static RSAPrivateKey generatePrivateKeyFromDER(byte[] keyBytes) throws InvalidKeySpecException, NoSuchAlgorithmException {
        PKCS8EncodedKeySpec spec = new PKCS8EncodedKeySpec(keyBytes);

        KeyFactory factory = KeyFactory.getInstance("RSA");

        return (RSAPrivateKey)factory.generatePrivate(spec);
    }

    public static X509Certificate generateCertificateFromDER(byte[] certBytes) throws CertificateException {
        CertificateFactory factory = CertificateFactory.getInstance("X.509");

        return (X509Certificate)factory.generateCertificate(new ByteArrayInputStream(certBytes));
    }
    public static byte[] fileToBytes(String filePath) {
        byte[] buffer = null;
        File file = new File(filePath);
        FileInputStream fis = null;
        ByteArrayOutputStream bos = null;
        try {
            fis = new FileInputStream(file);
            bos = new ByteArrayOutputStream();

            byte[] b = new byte[1024];
            int n;
            while ((n = fis.read(b)) != -1) {
                bos.write(b, 0, n);
            }
            buffer = bos.toByteArray();
        } catch (IOException e) {
            log.error(e.getMessage());
        } finally {
            try {
                if (null != bos) {
                    bos.close();
                }
            } catch (IOException e) {
                log.error(e.getMessage());
            } finally{
                try {
                    if(null!=fis){
                        fis.close();
                    }
                } catch (IOException e) {
                    log.error(e.getMessage());
                }
            }
        }
        return buffer;
    }
}
